#!/bin/bash

# ==============================================================================
# MySQL Instance Setup Script (v4 - Scorched Earth Cleanup)
# ==============================================================================

# --- 默认配置 ---
DEFAULT_USER="mysql"
DEFAULT_GROUP="mysql"
DEFAULT_START_PORT=3307
DEFAULT_ROOT_PASSWORD="test@2025"
CONFIG_DIR="/etc/my.cnf.d"
BASE_MOUNT_PATH="/mnt"

# --- 函数：显示用法 ---
usage() {
    echo "用法: $0 -n <实例数量> -c <NUMA节点列表> -D <设备路径列表> -f <配置文件路径>"
    echo "参数:"
    echo "  -n <数量>           要创建的 MySQL 实例数量 (必需)。"
    echo "  -c <列表>           用逗号分隔的 NUMA 节点列表 (必需)。"
    echo "  -D <列表>           用逗号分隔的【设备路径】列表 (必需)。"
    echo "  -f <文件路径>       包含额外MySQL参数的配置文件路径 (必需)。"
    echo "  [-p <密码>]         (可选) MySQL root 密码。"
    exit 1
}

# --- 解析命令行参数 ---
MYSQL_CONFIG_FILE=""
while getopts "n:c:D:p:f:h" opt; do
    case ${opt} in
        n) NUM_INSTANCES=$OPTARG ;;
        c) NUMA_NODES_STR=$OPTARG ;;
        D) DEVICE_PATHS_STR=$OPTARG ;;
        p) ROOT_PASSWORD=$OPTARG ;;
        f) MYSQL_CONFIG_FILE=$OPTARG ;;
        h) usage ;;
        *) usage ;;
    esac
done

ROOT_PASSWORD="${ROOT_PASSWORD:-$DEFAULT_ROOT_PASSWORD}"

# --- 验证必需的参数 ---
if [ -z "$NUM_INSTANCES" ] || [ -z "$NUMA_NODES_STR" ] || [ -z "$DEVICE_PATHS_STR" ] || [ -z "$MYSQL_CONFIG_FILE" ]; then
    usage
fi
if [ ! -f "$MYSQL_CONFIG_FILE" ]; then
    echo "错误: 找不到指定的配置文件: $MYSQL_CONFIG_FILE"
    exit 1
fi
if [[ $EUID -ne 0 ]]; then
   echo "错误: 此脚本必须以 root 身份运行。"
   exit 1
fi

IFS=',' read -r -a NUMA_NODES <<< "$NUMA_NODES_STR"
IFS=',' read -r -a DEVICE_PATHS <<< "$DEVICE_PATHS_STR"

if [ "${#NUMA_NODES[@]}" -ne "$NUM_INSTANCES" ] || [ "${#DEVICE_PATHS[@]}" -ne "$NUM_INSTANCES" ]; then
    echo "错误: NUMA 节点列表和设备路径列表的数量必须与实例数量 ($NUM_INSTANCES) 匹配。"
    exit 1
fi

# ==============================================================================
# 阶段 1: 超级清理 (焦土版)
# ==============================================================================
echo "--- 阶段 1: 正在执行超级清理 (焦土版)... ---"
# 1. 停止并禁用所有可能的 MySQL 服务
for i in {1..16}; do
    systemctl stop "mysql${i}" &>/dev/null
    systemctl disable "mysql${i}" &>/dev/null
    rm -f "/etc/systemd/system/mysql${i}.service"
    rm -f "/etc/my.cnf.d/mysql${i}.cnf"
done
systemctl daemon-reload
pkill -9 mysqld &>/dev/null
sleep 2

# 2. 暴力卸载和清理挂载点
echo "  正在清理所有潜在的测试挂载点..."
for i in {0..15}; do
    mount_point="${BASE_MOUNT_PATH}/disk${i}"
    if mountpoint -q "$mount_point"; then
        echo "    正在处理挂载点 ${mount_point}..."
        # [NEW] 使用 fuser 杀死所有占用该挂载点的进程
        fuser -km "$mount_point"
        sleep 1
        # [ENHANCED] 循环强制卸载
        for j in {1..10}; do
            umount -f -l "$mount_point" &>/dev/null
            if ! mountpoint -q "$mount_point"; then
                echo "    ${mount_point} 已成功卸载。"
                break
            fi
            echo "    卸载失败，1秒后重试..."
            sleep 1
        done
    fi
    # 确保目录被删除
    rm -rf "$mount_point"
    # 清理fstab以防万一
    sed -i "\|$mount_point|d" /etc/fstab
done
sleep 2
echo "清理完成。"
echo ""


# ==============================================================================
# 阶段 2: 准备磁盘和文件系统
# ==============================================================================
echo "--- 阶段 2: 准备磁盘和文件系统... ---"
echo "警告：自动化流程将格式化以下设备："
for device in "${DEVICE_PATHS[@]}"; do
    if findmnt -n --target / | grep -q "^${device}" || findmnt -n --target /boot | grep -q "^${device}"; then
        echo "!!! 致命错误: 设备 $device 是系统分区的一部分! 操作中止! !!!"
        exit 1
    fi
    echo "  - 设备: $device"
done

declare -a MOUNT_PATHS

for i in $(seq 0 $((${#DEVICE_PATHS[@]} - 1))); do
    device="${DEVICE_PATHS[$i]}"
    mount_point="${BASE_MOUNT_PATH}/disk${i}"
    MOUNT_PATHS+=($mount_point)

    echo "正在处理设备: $device -> 挂载到: $mount_point"

    # 1. 确保设备上没有任何分区被挂载
    lsblk -n -o MOUNTPOINT "${device}"* | grep -v "^$" | xargs -r umount -f -l

    # 2. 彻底销毁分区表和文件系统签名
    echo "  正在彻底销毁旧分区表和签名..."
    # [NEW] 擦除更大的区域以确保销毁所有元数据
    dd if=/dev/zero of="$device" bs=1M count=512 status=none
    wipefs -a "$device" &>/dev/null
    
    # 3. 创建新分区
    echo "  正在使用 parted 创建新分区表 (GPT) 和分区..."
    parted -s "$device" mklabel gpt
    parted -s "$device" mkpart primary 0% 100%
    
    # 4. 强制内核重新读取分区表
    echo "  正在强制内核同步分区变更..."
    sync
    blockdev --rereadpt "$device"
    partprobe "$device"
    # [NEW] 等待udev事件处理完毕
    udevadm settle
    sleep 2 # 额外等待

    partition="${device}1"
    if [[ "$device" == /dev/nvme*n* ]]; then
        partition="${device}p1"
    fi

    # 5. 格式化和挂载
    if [ ! -b "$partition" ]; then
        echo "错误: 分区 $partition 未能创建或检测到。中止。"
        exit 1
    fi

    echo "  正在格式化分区 $partition 为 xfs..."
    for k in {1..3}; do
        mkfs.xfs -f "$partition" &>/dev/null && break
        sleep 2
    done

    echo "  正在创建并挂载 $partition 到 $mount_point..."
    mkdir -p "$mount_point"
    mount -o noatime,nodiratime "$partition" "$mount_point"
    if ! mountpoint -q "$mount_point"; then
        echo "错误: 挂载 $mount_point 失败! 中止。"
        exit 1
    fi
done
echo "磁盘准备完成。"
echo ""

# ==============================================================================
# 阶段 3 & 4 (保持不变)
# ==============================================================================
# (此处省略未修改的阶段3和4的代码，请保留您原来的代码)
# ...
# --- 阶段 3: 创建和初始化 MySQL 实例... ---
echo "--- 阶段 3: 创建和初始化 MySQL 实例... ---"
mkdir -p "$CONFIG_DIR"
BASE_CONFIG_FILE="mysql_configs/base.cnf"
for i in $(seq 1 $NUM_INSTANCES); do
    instance_num=$i
    instance_name="mysql${instance_num}"
    port=$((DEFAULT_START_PORT + i - 1))
    numa_node="${NUMA_NODES[$i-1]}"
    base_path="${MOUNT_PATHS[$i-1]}"
    data_dir="${base_path}/data"
    log_dir="${base_path}/logs"
    error_log_file="${log_dir}/error.log"
    echo "--- 正在设置实例: ${instance_name} (端口: ${port}, NUMA: ${numa_node}) ---"
    echo "    使用配置文件: ${MYSQL_CONFIG_FILE}"
    mkdir -p "$data_dir" "$log_dir"
    chown -R "${DEFAULT_USER}:${DEFAULT_GROUP}" "$base_path"
    chmod -R 750 "$base_path"
    config_file="${CONFIG_DIR}/${instance_name}.cnf"
    socket_file="${data_dir}/mysql.sock"
    pid_file="${data_dir}/${instance_name}.pid"
    cat << EOF > "$config_file"
[mysqld]
port=${port}
datadir=${data_dir}
socket=${socket_file}
pid-file=${pid_file}
user=${DEFAULT_USER}
log_error=${error_log_file}
innodb_log_group_home_dir=${log_dir}
EOF
    if [ -f "$BASE_CONFIG_FILE" ]; then
        echo "" >> "$config_file"; cat "$BASE_CONFIG_FILE" >> "$config_file"; fi
    echo "" >> "$config_file"; cat "$MYSQL_CONFIG_FILE" >> "$config_file"
    echo "" >> "$config_file"; cat << EOF >> "$config_file"
[client]
socket=${socket_file}
EOF
    echo "  正在初始化 MySQL 数据目录..."
    if ! mysqld --defaults-file="$config_file" --initialize-insecure --user="${DEFAULT_USER}" >/dev/null 2>&1; then
        echo "错误: 初始化 ${instance_name} 失败。"
        if [ -f "$error_log_file" ]; then
            echo "--- ${instance_name} 的错误日志 (${error_log_file}) 内容如下: ---"
            cat "$error_log_file"
            echo "------------------------------------------------------------"
        else
            echo "错误日志文件 ${error_log_file} 未找到。"
        fi
        exit 1
    fi
    service_file="/etc/systemd/system/${instance_name}.service"
    cat << EOF > "$service_file"
[Unit]
Description=MySQL Server Instance ${instance_num} (NUMA Node ${numa_node})
After=network.target
[Service]
User=${DEFAULT_USER}
Group=${DEFAULT_GROUP}
ExecStart=/usr/bin/numactl --cpunodebind=${numa_node} --membind=${numa_node} /usr/sbin/mysqld --defaults-file=${config_file}
LimitNOFILE=65535
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
done

# --- 阶段 4: 启动实例并配置密码和权限... ---
echo ""
echo "--- 阶段 4: 启动实例并配置密码和权限... ---"
systemctl daemon-reload
for i in $(seq 1 $NUM_INSTANCES); do
    instance_name="mysql${i}"
    systemctl start "$instance_name"
    systemctl enable "$instance_name"
done
echo "  等待实例启动 (15秒)..."
sleep 15
for i in $(seq 1 $NUM_INSTANCES); do
    port=$((DEFAULT_START_PORT + i - 1))
    base_path="${MOUNT_PATHS[$i-1]}"
    socket_file="${base_path}/data/mysql.sock"
    if ! [ -S "$socket_file" ]; then
        echo "  警告：Socket 文件 $socket_file 不存在。跳过实例 mysql${i} 的配置。"
        continue
    fi
    echo "  正在为端口 ${port} 的实例配置 root 权限..."
    SQL_COMMANDS="
    ALTER USER 'root'@'localhost' IDENTIFIED BY '${ROOT_PASSWORD}';
    CREATE USER IF NOT EXISTS 'root'@'127.0.0.1' IDENTIFIED BY '${ROOT_PASSWORD}';
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION;
    FLUSH PRIVILEGES;
    "
    if ! mysql --socket="$socket_file" -uroot -e "${SQL_COMMANDS}"; then
        echo "  错误: 为实例 (端口 ${port}) 设置初始权限失败! 请检查mysql客户端输出。"
    else
        echo "    - 实例 (端口 ${port}) 权限设置成功。"
    fi
done
echo ""
echo "所有 MySQL 实例已安装、启动并配置完毕！"